import { Provide, Inject } from "@midwayjs/core";
import { BaseService, CoolCommException } from "@cool-midway/core";
import { InjectEntityModel } from "@midwayjs/typeorm";
import { Repository } from "typeorm";
import { OrderInfoEntity } from "../entity/info";
import { OrderItemEntity } from "../entity/item";
import { ProviderManualOrderDTO } from "../dto/info";
import { Utils } from "../../../comm/utils";
import { Context } from "@midwayjs/koa";
import { UserInfoEntity } from "../../user/entity/info";
import { OrderAssignEntity } from "../entity/assign";

@Provide()
export class OrderManualService extends BaseService {
    @InjectEntityModel(OrderInfoEntity)
    orderInfoEntity: Repository<OrderInfoEntity>;

    @InjectEntityModel(OrderItemEntity)
    orderItemEntity: Repository<OrderItemEntity>;

    @InjectEntityModel(OrderAssignEntity)
    orderAssignEntity: Repository<OrderAssignEntity>;

    @InjectEntityModel(UserInfoEntity)
    userInfoEntity: Repository<UserInfoEntity>;

    @Inject()
    utils: Utils;

    @Inject()
    ctx: Context;

    /**
     * 服务人员手动录入订单
     */
    async createByProvider(dto: ProviderManualOrderDTO) {
        const providerId = this.ctx?.provider?.id;
        if (!providerId) {
            throw new CoolCommException('登录失效，请重新登录');
        }
        if (!dto?.items?.length) {
            throw new CoolCommException('请至少配置一个子订单');
        }

        const user = await this.userInfoEntity.findOne({ where: { id: dto.userId } });
        if (!user) {
            throw new CoolCommException('用户不存在');
        }

        const orderNo = this.utils.generateUniqueId('ORDER');

        return await this.orderInfoEntity.manager.transaction(async manager => {
            const normalizedItems = this.normalizeItems(dto.items || []);
            const now = new Date().toISOString();

            const totalAmount = normalizedItems.reduce((sum, item) => this.utils.add(sum, item.amount), 0);
            const finalAmount = dto.orderAmount ?? totalAmount;

            const order = await manager.getRepository(OrderInfoEntity).save({
                orderNo,
                type: dto.type,
                cover: dto.cover || null,
                price: finalAmount,
                status: dto.status,
                userId: dto.userId,
                remark: dto.remark || null,
                source: 3,
                createdByProviderId: providerId,
            });

            const savedItems = await manager.getRepository(OrderItemEntity).save(
                normalizedItems.map(item => ({
                    ...item,
                    orderId: order.id,
                    fulfillStatus: 1,
                    fulfillStatusTime: now,
                }))
            );

            await manager.getRepository(OrderAssignEntity).insert(
                savedItems.map(item => ({
                    orderId: order.id,
                    itemId: item.id,
                    providerId,
                    status: 1,
                    assignedTime: now,
                    executeStatus: 0,
                }))
            );

            return {
                orderId: order.id,
                orderNo: order.orderNo,
                status: order.status,
                price: order.price,
                source: order.source,
                canSharePay: order.status === 0,
            };
        });
    }

    /**
     * 子订单数据校验与格式化
     */
    private normalizeItems(items: any[]) {
        if (!Array.isArray(items) || !items.length) {
            throw new CoolCommException('请至少配置一个子订单');
        }
        return items.map((raw, index) => {
            if (!raw || typeof raw !== 'object') {
                throw new CoolCommException(`第${index + 1}个子订单数据不合法`);
            }
            const title = (raw.title || '').toString().trim();
            if (!title) {
                throw new CoolCommException(`第${index + 1}个子订单标题不能为空`);
            }
            const unitPrice = this.parsePositiveNumber(raw.unitPrice, `第${index + 1}个子订单单价`);
            const quantity = this.parsePositiveInteger(raw.quantity ?? 1, `第${index + 1}个子订单数量`);
            const amountValue = raw.amount ?? this.utils.mul(unitPrice, quantity);
            const amount = this.parsePositiveNumber(amountValue, `第${index + 1}个子订单金额`);
            const productId = this.parseOptionalNumber(raw.productId);
            const productItemId = this.parseOptionalNumber(raw.productItemId);
            const extra = this.normalizeExtra(raw.extra);
            return {
                title,
                unitPrice,
                quantity,
                amount,
                productId,
                productItemId,
                useTime: raw.useTime || null,
                startPlace: raw.startPlace || null,
                endPlace: raw.endPlace || null,
                extra,
            };
        });
    }

    private parsePositiveNumber(value: any, label: string) {
        const num = Number(value);
        if (!Number.isFinite(num) || num <= 0) {
            throw new CoolCommException(`${label}必须为大于0的数字`);
        }
        return num;
    }

    private parsePositiveInteger(value: any, label: string) {
        const num = Number(value);
        if (!Number.isFinite(num) || num <= 0 || !Number.isInteger(num)) {
            throw new CoolCommException(`${label}必须为正整数`);
        }
        return num;
    }

    private parseOptionalNumber(value: any) {
        if (value === undefined || value === null || value === '') {
            return null;
        }
        const num = Number(value);
        if (!Number.isFinite(num)) {
            throw new CoolCommException('产品ID或产品项ID必须为数字');
        }
        return num;
    }

    private normalizeExtra(extra: any) {
        if (extra === undefined || extra === null || extra === '') {
            return null;
        }
        if (typeof extra === 'string') {
            try {
                return JSON.parse(extra);
            } catch (err) {
                throw new CoolCommException('子订单附加信息extra必须为JSON对象');
            }
        }
        if (typeof extra !== 'object') {
            throw new CoolCommException('子订单附加信息extra必须为JSON对象');
        }
        return extra;
    }
}


